Devlog: How this site works
Mini intro
Here I will explain some general structure of the project. I will not discuss games (because it is almost the same as a blog) or some trivial things that are not relevant, but how the project is structured, what I use, why, etc. And since I explained the motivation behind creating a site like this on the homepage, it would be best to now explain how it actually works. Once you understand how the generation works, you can see that with a few small automation scripts I can directly place files from Obsidian as blog posts on my site.
Project structure
.
├── content/
│ ├── blog/
│ │ └── blog.md
│ ├── index.md
│ └── projekti.md
│
├── src/
│ ├── blog.rs
│ ├── main.rs
│ ├── models.rs
│ └── utils.rs
├── static/
│ ├── blog/
│ ├── favicon/
│ └── style.css
└── templates/
├── 404.html
├── blog_list.html
└── base.html
Content
Inside the content folder there are .md files that are taken and converted into HTML pages. the entire blog folder is viewed, and pages are created dynamically, while everything outside the blog folder is manually added.
SRC
Folder where there are scripts that generate all this, so let's go through what it does:
-
main.rs At the beginning, it creates the project structure inside the public folder. It then uses a function to copy static files (such as CSS files, images, favicons) from the static folder. It then initializes the mini-environment and loads the basic HTML templates from the templates folder. It manually calls the base page generation (index.md becomes index.html), and finally calls the blog creation function to handle those specific sections of the site.
-
blog.rs Goes through the content/blog/ folder and finds all .md files. It then reads each file line by line looking for the first title (the line starting with # ) to use as the title of the blog post. It calls the build_page function to convert that Markdown to HTML and save it to public/blog/file_name.html. It gathers all the post data (title and URL/slug) into a list, inserts it into the blog_list template, and then wraps that content into the main base template to create the main public/blog.html page (blog archive).
-
models.rs Contains the BlogPost structure in which the title and slug fields are. It uses the Serde library, which is necessary for the template engine (miniature) to be able to read this data and print it in HTML (eg for generating a list of links).
-
utils.rs It has 2 functions. The first is a recursive function that copies the entire folder with all its subfolders and files from one location to another (used in main.rs to copy static resources). The second is a universal function for creating an individual page; receives the path to the .md file, reads it, parses Markdown into HTML, fills the base template with that content and saves it to the specified output .html path. It also receives a root_path variable (eg "../") so that relative links for CSS and images inside subfolders work correctly.
Static
All static elements such as CSS files, images, favicons, etc. are located here.
Templates
Inside this folder there are page templates. For example, this is the main page template:
<!DOCTYPE html>
<html lang="hr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LukasWorkshop</title>
<link rel="icon" type="image/x-icon" href="{{ root_path }}slike/favicon/favicon.ico">
<link rel="stylesheet" href="{{ root_path }}style.css">
</head>
<body>
<div class="container">
<header>
<nav>
<ul>
<li><a href="{{ root_path }}index.html">~/main</a></li>
<li><a href="{{ root_path }}blog.html">~/blog</a></li>
<li><a href="{{ root_path }}igre.html">~/games</a></li>
<li><a href="{{ root_path }}projects.html">~/projects</a></li>
</ul>
</nav>
</header>
<main>
{{ content | safe }}
</main>
<footer>
<p>Designed and made: Luka Prlić</p>
<p>Copyright: © 2026. All rights reserved.</p>
</footer>
</div>
</body>
</html>